package com.samphanie.admin.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.samphanie.admin.modules.sys.domain.vo.MenuVo;
import com.samphanie.admin.modules.sys.domain.vo.RouteVo;
import com.samphanie.admin.modules.sys.service.IMenuService;
import com.samphanie.common.constants.SystemConstants;
import com.samphanie.mbg.mapper.sys.SysMenuMapper;
import com.samphanie.mbg.model.sys.SysMenu;
import com.samphanie.mbg.utils.PageUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author ZSY
 */
@Service
public class MenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements IMenuService {

    /**
     * 菜单分页列表
     *
     * @return PageUtils
     */
    @Override
    public PageUtils listPage(Map<String, Object> query) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(SysMenu::getSort).orderByDesc(SysMenu::getCreateTime);

        PageUtils.startPage(query);
        List<SysMenu> list = list(queryWrapper);
        return new PageUtils(list);
    }

    /**
     * 树形菜单列表
     *
     * @return List<MenuVo>
     */
    @Override
    public List<MenuVo> menuTreeList() {
        List<SysMenu> sysMenuList = this.list();
        return this.recursionMenuForTree(sysMenuList, SystemConstants.ROOT_VALUE);
    }

    /**
     * 菜单详情
     *
     * @return MenuVo
     */
    @Override
    public MenuVo queryMenuVoById(Long menuId) {
        SysMenu sysMenu = this.getById(menuId);
        MenuVo menuVo = new MenuVo();
        BeanUtils.copyProperties(sysMenu, menuVo);
        return menuVo;
    }

    /**
     * 获取所有路由列表
     *
     * @return List<RouteVo>
     */
    @Override
    public List<RouteVo> queryDynamicRoutes() {
        List<SysMenu> menuList = this.queryMenuList();
        return recursionRouterList(SystemConstants.ROOT_VALUE, menuList);
    }

    /**
     * 查询菜单列表
     *
     * @return List<SysMenu>
     */
    @Override
    public List<SysMenu> queryMenuList() {
        return list();
    }

    /**
     * 递归组装 MenuVo
     *
     * @param menuList 菜单数据
     * @param parentId 菜单父ID
     * @return List<MenuVo>
     */
    private List<MenuVo> recursionMenuForTree(List<SysMenu> menuList, Long parentId) {
        List<MenuVo> menuVoList = new ArrayList<>();
        Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .forEach(menu -> {
                    MenuVo menuVo = new MenuVo();
                    BeanUtil.copyProperties(menu, menuVo);
                    List<MenuVo> children = recursionMenuForTree(menuList, menu.getId());
                    if (CollectionUtil.isNotEmpty(children)) {
                        menuVo.setChildren(children);
                    }
                    menuVoList.add(menuVo);
                });
        return menuVoList;
    }

    /**
     * 递归组装路由数据
     *
     * @param parentId 菜单上级ID
     * @param menuList 菜单列表
     * @return List<RouteVo>
     */
    private List<RouteVo> recursionRouterList(Long parentId, List<SysMenu> menuList) {
        List<RouteVo> routeVoList = new ArrayList<>();
        menuList.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .forEach(menu -> {
                    RouteVo build = RouteVo.builder()
                            .parentId(menu.getParentId())
                            .name(menu.getName())
                            .path(menu.getPath())
                            .icon(menu.getIcon())
                            .component(menu.getComponent())
                            .build();
                    // 遍历出子路由
                    List<RouteVo> routerChildrenList = this.recursionRouterList(menu.getId(), menuList);
                    build.setChildren(routerChildrenList);
                    routeVoList.add(build);
                });
        return routeVoList;
    }
}




